{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "手动验证GlobalAveragePooling2D运算方式\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "from tensorflow.keras import Sequential,Model\n",
    "from tensorflow.keras.layers import Conv2D,MaxPool2D,GlobalAveragePooling2D,Dense,Dropout\n",
    "from tensorflow.keras.datasets.fashion_mnist import load_data\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "from PIL import Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入图shape： (16, 16)\n",
      "输入图： [[253 254 255 255 250 255 218  20 142 255 255 255 250 255 254 253]\n",
      " [255 255 249 255 255 255 156   0  78 250 255 252 254 255 249 255]\n",
      " [254 249 255 252 255 251 172   0  93 250 250 255 255 253 254 251]\n",
      " [255 250 255 247 255 245 164   0  80 255 255 255 253 248 255 255]\n",
      " [254 255 255 250 250 255 176   0  88 255 250 247 255 255 255 253]\n",
      " [255 255 252 255 210 155 160   9 111 162 171 251 255 253 255 255]\n",
      " [255 250 250 255 185  10  31   0  21  12  85 250 255 248 255 251]\n",
      " [255 247 255 184  74   1   0   0   0   1  23 146 219 255 254 255]\n",
      " [254 143  26   0   0   0  19   0   4  22   0   0   0  54 155 254]\n",
      " [ 76  14  27 113 177 222 191   1  45 232 203 149  93  19   9  61]\n",
      " [203 237 255 255 255 255 220   1  41 255 254 255 255 249 238 193]\n",
      " [252 255 252 243 255 255 237   0  54 254 252 253 255 255 255 248]\n",
      " [255 254 251 255 255 252 248   3  71 252 255 255 255 246 252 255]\n",
      " [252 255 255 252 244 255 247   2  82 255 255 247 254 255 255 237]\n",
      " [255 244 255 255 255 254 184   0  30 201 255 251 255 252 253 255]\n",
      " [252 255 252 254 245 120   0   2   0   8 151 254 255 255 255 249]]\n",
      "输入图shape： (16, 16, 1)\n"
     ]
    }
   ],
   "source": [
    "path=r\"C:\\Users\\mym\\Desktop\\文件接收柜\\feiji.jpg\"\n",
    "im = Image.open(path)\n",
    "img=np.array(im)\n",
    "print('输入图shape：',img.shape)\n",
    "print('输入图：',img)\n",
    "img=img.reshape(img.shape[0],img.shape[1],1)\n",
    "# img=np.expand_dims(img,-1)\n",
    "print('输入图shape：',img.shape)\n",
    "# print('输入图：',img)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(16, 16, 1)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "input_shape=img.shape\n",
    "input_shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入图shape： (1, 16, 16, 1)\n"
     ]
    }
   ],
   "source": [
    "# 转换图片格式为：(数量,高,宽,channel)\n",
    "img_batch=img.reshape(1,input_shape[0],input_shape[1],input_shape[2])\n",
    "print('输入图shape：',img_batch.shape)\n",
    "# print(img_batch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_4\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_2 (Conv2D)            (None, 16, 16, 8)         80        \n",
      "_________________________________________________________________\n",
      "max_pooling2d_4 (MaxPooling2 (None, 8, 8, 8)           0         \n",
      "_________________________________________________________________\n",
      "global_average_pooling2d_4 ( (None, 8)                 0         \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 10)                90        \n",
      "=================================================================\n",
      "Total params: 170\n",
      "Trainable params: 170\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model=Sequential()\n",
    "\"\"\"\n",
    "第一层用卷积层，提取图片特征\n",
    "\"\"\"\n",
    "conv2d=Conv2D(8,(3,3),input_shape=input_shape,activation='relu',padding=\"same\")\n",
    "model.add(conv2d)\n",
    "\n",
    "model.add(MaxPool2D())\n",
    "# model.add(Dropout(0.5))\n",
    "\n",
    "\"\"\"\n",
    "关键代码：GAP层\n",
    "\"\"\"\n",
    "model.add(GlobalAveragePooling2D())\n",
    "\n",
    "model.add(Dense(10,activation='softmax'))\n",
    "\n",
    "\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 定义输出模型，输出MaxPool2D层，GAP层，Dense层结果\n",
    "out_model=Model(inputs=[model.input],outputs=[model.layers[1].output,model.layers[2].output,model.layers[3].output])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运算并返回3个结果，按序分别是：MaxPool2D层，GAP层，Dense层结果\n",
    "mp_result,gap_result,dense_result=out_model.predict(img_batch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mp_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[14.068799 ,  6.6156116, 69.199905 , 94.24501  ,  3.0666184,\n",
       "         2.3944912, 25.9354   , 19.52853  ]], dtype=float32)"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看GAP层结果\n",
    "gap_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 8, 8, 8)"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mp_result.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "上面的mp_result是MaxPool2D层的结果，每一列是一个特征图结果，所以要做转换\n",
    "\"\"\"\n",
    "mp_list=[]\n",
    "for item in range(mp_result.shape[-1]):\n",
    "    img=mp_result[:,:,:,item]\n",
    "    img=img.reshape(mp_result.shape[1],mp_result.shape[2])\n",
    "    print(img)\n",
    "    print(\"----\")\n",
    "    mp_list.append(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "14.068798661231995\n",
      "6.615610986948013\n",
      "69.19990396499634\n",
      "94.2449951171875\n",
      "3.066618651151657\n",
      "2.3944912403821945\n",
      "25.93540132045746\n",
      "19.52852690219879\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "对每个MaxPool2D层的结果求平均值\n",
    "然后与gap_result值做比较\n",
    "\"\"\"\n",
    "for item in mp_list:\n",
    "    print(sum(sum(item))/(item.shape[0]*item.shape[1]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
